package org.dromara.system.utils;

import com.alibaba.fastjson2.JSONObject;
import okhttp3.*;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.system.constants.OrderConstants;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class RequestUtils {

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
    public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36";

    public static void main(String[] args) {

//        String str = "{\n" +
//            "  \"accountId\": 909,\n" +
//            "  \"billing\": {\n" +
//            "    \"address_1\": \"2312 Eisenhower Dr N2558 Putnam street\",\n" +
//            "    \"address_2\": \"\",\n" +
//            "    \"city\": \"Schenectadu\",\n" +
//            "    \"country\": \"DE\",\n" +
//            "    \"email\": \"liaoxw0310@gmail.com\",\n" +
//            "    \"first_name\": \"Linda\",\n" +
//            "    \"last_name\": \"ryan rosamino\",\n" +
//            "    \"phone\": \"5183629733\",\n" +
//            "    \"postcode\": \"12304\",\n" +
//            "    \"state\": \"New York\"\n" +
//            "  },\n" +
//            "  \"callback_url\": \"https://salestores.shop/homeapi/checkouts/server/nexpay/callback\",\n" +
//            "  \"cancel_url\": \"https://salestores.shop/137458-03eb25/one-page-checkouts/03eb25230a43f65b5d76e8f2a0c3191d?previous_step=shipping_method&step=payment_method\",\n" +
//            "  \"createLink\": null,\n" +
//            "  \"currency\": \"EUR\",\n" +
//            "  \"customer_ip_address\": \"156.59.13.139\",\n" +
//            "  \"device\": null,\n" +
//            "  \"failure_url\": \"https://salestores.shop/checkouts/clientcallback/nexpay?order_number=137458-257521\",\n" +
//            "  \"from_domain\": \"https://salestores.shop\",\n" +
//            "  \"linkCode\": null,\n" +
//            "  \"mchid\": 10666,\n" +
//            "  \"orderNo\": null,\n" +
//            "  \"order_id\": \"137458-257521\",\n" +
//            "  \"payType\": \"stripe\",\n" +
//            "  \"product_data\": [\n" +
//            "    {\n" +
//            "      \"attributes\": \"color: blacksize: 36\",\n" +
//            "      \"image\": \"https://cdn.statics-cdn-link.com/uploads/137458/cart/resources/20250331/C247C90A-A98C-C331-C638-BC9603036600.jpg\",\n" +
//            "      \"post_id\": \"2829668\",\n" +
//            "      \"post_name\": \"Allround shoes e.s. Toledo low\",\n" +
//            "      \"price\": 22.58,\n" +
//            "      \"quantity\": 1,\n" +
//            "      \"type\": \"simple\"\n" +
//            "    }\n" +
//            "  ],\n" +
//            "  \"rates\": null,\n" +
//            "  \"shipping\": {\n" +
//            "    \"address_1\": \"2312 Eisenhower Dr N2558 Putnam street\",\n" +
//            "    \"address_2\": \"\",\n" +
//            "    \"city\": \"Schenectadu\",\n" +
//            "    \"country\": \"DE\",\n" +
//            "    \"email\": \"liaoxw0310@gmail.com\",\n" +
//            "    \"first_name\": \"Linda\",\n" +
//            "    \"last_name\": \"ryan rosamino\",\n" +
//            "    \"phone\": \"5183629733\",\n" +
//            "    \"postcode\": \"12304\",\n" +
//            "    \"state\": \"New York\"\n" +
//            "  },\n" +
//            "  \"success_url\": \"https://salestores.shop/checkouts/success/03eb25230a43f65b5d76e8f2a0c3191d?financial_status=230\",\n" +
//            "  \"total\": 32.58,\n" +
//            "  \"usdMoney\": null,\n" +
//            "  \"version\": \"v1\",\n" +
//            "  \"xtPlugin\": \"nexpay\"\n" +
//            "}";
//        String res = new RequestUtils().doPostJsonByToken("https://luxusnzm.com", str);
//        System.out.println(res);



        // 发起第一次即时通知
        String reqStr;
        String secret = "ee2fc03b5be5404894884e9290428fdc";
        try {
            Map<String, String> headers = new HashMap<>();
            String str = "{\n" +
                "  \"order_id\": \"15711\",\n" +
                "  \"pay_status\": \"success\",\n" +
                "  \"pay_no\": \"20250512184957774461\",\n" +
                "  \"fail_message\": \"\"\n" +
                "}";
            if (StringUtils.isNotEmpty(secret)) {
                headers.put(OrderConstants.signature, EncryptUtils.encryptByMd5(str + secret).toUpperCase(Locale.ROOT));
            }
            reqStr = new RequestUtils().doPostJsonNoTry("https://www.mjsmedicals.com/wp-json/wc-nexpay/v1/callback", str, headers);
        } catch (Exception e) {
            reqStr = "回调请求失败：" + e.getMessage();
        }

        System.out.println(reqStr);
   }

    /**
     * 获取IP国家信息
     *
     * @param url   地址
     * @param key   key
     * @param ip    ip
     * @param agent 指纹
     * @return
     */
    public String getIpContry(String url, String key, String ip, String agent) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url + "20230615_iM5b2flma")  // 示例 ID实际使用时需要替换为实际的 ID
                .addHeader("escloak-key", key)
                .addHeader("User-Agent", agent)
                .post(RequestBody.create(JSON, getJsonBody(ip, agent)))
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                System.out.println("请求失败: " + response);
            }
        } catch (IOException e) {
            System.out.println("http请求失败：" + e.getMessage());
//            e.printStackTrace();
        }
        return null;
    }

    private static String getJsonBody(String ip, String userAgent) {
        return new JSONObject().fluentPut("visitor", new JSONObject().fluentPut("remote_addr", ip).fluentPut("v", 4).fluentPut("xi", 1).fluentPut("lp_url", "http://" + ip))
                .fluentPut("browser_headers", new JSONObject().fluentPut("user_vvagent", userAgent).fluentPut("host", ip))
                .fluentPut("client_server", new JSONObject().fluentPut("REMOTE_ADDR", ip).fluentPut("SERVER_ADDR", ip)).toString();
    }

    /**
     * get 请求
     *
     * @param url 请求url地址
     * @return string
     */
    public String doGet(String url) {
        return doGet(url, null, null);
    }

    public byte[] doGetByte(String url) {
        return doGetByte(url, null, null);
    }

    public String doPost(String url) {
        return doPost(url, null, null);
    }

    /**
     * get 请求
     *
     * @param url    请求url地址
     * @param params 请求参数 map
     * @return string
     */
    public String doGetToParams(String url, Map<String, String> params) {
        return doGet(url, params, null);
    }

    /**
     * get 请求
     *
     * @param url     请求url地址
     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     */
    public String doGetToHeaders(String url, Map<String, String> headers) {
        return doGet(url, null, headers);
    }

    /**
     * get 请求
     *
     * @param url     请求url地址
     * @param params  请求参数 map
     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     */
    public String doGet(String url, Map<String, String> params, Map<String, String> headers) {
        StringBuilder sb = new StringBuilder(url);
        if (params != null && params.keySet().size() > 0) {
            boolean firstFlag = true;
            for (String key : params.keySet()) {
                if (firstFlag) {
                    sb.append("?").append(key).append("=").append(params.get(key));
                    firstFlag = false;
                } else {
                    sb.append("&").append(key).append("=").append(params.get(key));
                }
            }
        }
        Request.Builder builder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                builder.addHeader(header, headers.get(header));
            }
        }
        Request request = builder.url(sb.toString()).build();

        return executeBody(request);
    }

    public byte[] doGetByte(String url, Map<String, String> params, Map<String, String> headers) {
        StringBuilder sb = new StringBuilder(url);
        if (params != null && params.keySet().size() > 0) {
            boolean firstFlag = true;
            for (String key : params.keySet()) {
                if (firstFlag) {
                    sb.append("?").append(key).append("=").append(params.get(key));
                    firstFlag = false;
                } else {
                    sb.append("&").append(key).append("=").append(params.get(key));
                }
            }
        }
        Request.Builder builder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                builder.addHeader(header, headers.get(header));
            }
        }
        Request request = builder.url(sb.toString()).build();

        return executeByte(request);
    }

    /**
     * post 请求
     *
     * @param url    请求url地址
     * @param params 请求参数 map
     * @return string
     */
    public String doPostForm(String url, Map<String, String> params) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        return execute(request);
    }

    /**
     * post 请求
     *
     * @param url    请求url地址
     * @param params 请求参数 map
     * @return string
     */
    public String doPostFormByToken(String url, Map<String, String> params) {
        Map<String, String> headers = new HashMap<>();
        headers.put(OrderConstants.token_name, getToken(url));
        return doPost(url, params, headers);
    }

    /**
     * post 请求
     *
     * @param url     请求url地址
     * @param params  请求参数 map
     * @param headers 请求头字段 {k1:v1, k2: v2, ...}
     * @return string
     */
    public String doPostByToken(String url, Map<String, String> params, Map<String, String> headers) {
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put(OrderConstants.token_name, getToken(url));
        return doPost(url, params, headers);
    }


    /**
     * post 请求, 请求数据为 json 的字符串
     *
     * @param url  请求url地址
     * @param json 请求数据, json 字符串
     * @return string
     */
    public String doPostJsonByToken(String url, String json) {
        Map<String, String> headers = new HashMap<>();
        headers.put(OrderConstants.token_name, getToken(url));
        return executePost(url, json, JSON, headers);
    }

    /**
     * post 请求
     *
     * @param url     请求url地址
     * @param params  请求参数 map
     * @param headers 请求头字段 {k1:v1, k2: v2, ...}
     * @return string
     */
    public String doPost(String url, Map<String, String> params, Map<String, String> headers) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request.Builder requestBuilder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                requestBuilder.addHeader(header, headers.get(header));
            }
        }
        Request request = requestBuilder.url(url).post(builder.build()).build();
        return execute(request);
    }

    /**
     * post 请求, 请求数据为 json 的字符串
     *
     * @param url  请求url地址
     * @param json 请求数据, json 字符串
     * @return string
     */
    public String doPostJson(String url, String json) {
        return executePost(url, json, JSON, new HashMap<>());
    }

    /**
     * post 请求, 请求数据为 json 的字符串
     *
     * @param url     请求url地址
     * @param json    请求数据, json 字符串
     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     */
    public String doPostJson(String url, String json, Map<String, String> headers) {

        RequestBody requestBody = RequestBody.create(JSON, json);
        Request.Builder builder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                builder.addHeader(header, headers.get(header));
            }
        }
        Request request = builder.url(url).post(requestBody).build();
        return execute(request);
    }

    /**
     * post 请求, 请求数据为 json 的字符串
     *
     * @param url     请求url地址
     * @param json    请求数据, json 字符串
     * @return string
     */
    public String doPostJsonNoTry(String url, String json) throws Exception {
        return doPostJsonNoTry(url, json, null);
    }

    /**
     * post 请求, 请求数据为 json 的字符串
     *
     * @param url     请求url地址
     * @param json    请求数据, json 字符串
     * @param headers 请求头字段 {k1, v1 k2, v2, ...}
     * @return string
     */
    public String doPostJsonNoTry(String url, String json, Map<String, String> headers) throws Exception {

        RequestBody requestBody = RequestBody.create(JSON, json);
        Request.Builder builder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                builder.addHeader(header, headers.get(header));
            }
        }
        Request request = builder.url(url).post(requestBody).build();
        return executeNoTry(request);
    }

    /**
     * post 请求, 请求数据为 xml 的字符串
     *
     * @param url 请求url地址
     * @param xml 请求数据, xml 字符串
     * @return string
     */
    public String doPostXml(String url, String xml) {

        return executePost(url, xml, XML, new HashMap<>());
    }

    public String executePost(String url, String data, MediaType contentType, Map<String, String> headers) {
        RequestBody requestBody = RequestBody.create(contentType, data);

        Request.Builder requestBuilder = new Request.Builder();
        if (headers != null && !headers.isEmpty()) {
            for (String header : headers.keySet()) {
                requestBuilder.addHeader(header, headers.get(header));
            }
        }

        Request request = requestBuilder.url(url).post(requestBody).build();
        return execute(request);
    }

    public String execute(Request request) {
        Response response = null;
        try {

            OkHttpClient client = createUnsafeOkHttpClient();
//            OkHttpClient client = new OkHttpClient.Builder()
//                    .readTimeout(2 * 60, TimeUnit.SECONDS) // 读取超时时间为 30 秒
//                    .build();

            response = client.newCall(request).execute();
            if (response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            System.out.println("http请求失败：" + e.getMessage());
//            e.printStackTrace();
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return "";
    }

    public String executeNoTry(Request request) throws Exception {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS) // 连接超时时间为 30 秒
                .writeTimeout(30, TimeUnit.SECONDS)   // 写入超时时间为 30 秒
                .readTimeout(30, TimeUnit.SECONDS) // 读取超时时间为 30 秒
                .build();

        Response response = null;
        try {
            response = client.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                return response.body().string();
            }
        }catch (Exception e) {
            System.out.println("http请求失败：" + e.getMessage());
            throw e;
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return "";
    }

    public String executeBody(Request request) {
        Response response = null;
        try {
            response = new OkHttpClient().newCall(request).execute();
            if (response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            System.out.println("http请求失败：" + e.getMessage());
//            e.printStackTrace();

        } finally {
            if (response != null) {
                response.close();
            }
        }
        return "";
    }

    public String executeHttp(String url) {
        Response response = null;
        try {
            response = new OkHttpClient().newCall(new Request.Builder().url(url).build()).execute();
            if (response.body() != null) {
                return response.body().string();
            }
        } catch (Exception e) {
            System.out.println("http请求失败：" + e.getMessage());
//            e.printStackTrace();

        } finally {
            if (response != null) {
                response.close();
            }
        }
        return "";
    }

    public byte[] executeByte(Request request) {
        Response response = null;
        try {
            response = new OkHttpClient().newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().bytes();
            }
        } catch (Exception e) {
            System.out.println("http请求失败：" + e.getMessage());
//            e.printStackTrace();
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }

    public OkHttpClient createUnsafeOkHttpClient() {
        try {
            // 创建一个不校验任何证书的 TrustManager
            final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
            };

            // 安装所有证书为受信任的
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // 创建 OkHttpClient 并使用不安全的 SSLSocketFactory
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier((hostname, session) -> true); // 不校验主机名
            builder.connectTimeout(2 * 60, TimeUnit.SECONDS);// 连接超时时间为 30 秒
            builder.readTimeout(2 * 60, TimeUnit.SECONDS); // 读取超时时间为 30 秒

            return builder.build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getToken(String url) {
        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put("iss", "https://nexpaysystem.com");
        claimsMap.put("aud", url);
//        claimsMap.put("iat", LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000);
//        claimsMap.put("nbf", LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000);
//        claimsMap.put("exp", LocalDateTime.now().plusMinutes(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000);

        claimsMap.put("iat", Instant.now().getEpochSecond());
        claimsMap.put("nbf", Instant.now().getEpochSecond());
        claimsMap.put("exp", Instant.now().plus(1, ChronoUnit.DAYS).getEpochSecond());

        return JwtUtils.createToken(claimsMap);
    }
}
